package com.yycx.module.bus.provider.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.security.OpenUser;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.PinyinUtil;
import com.yycx.module.bus.client.entity.*;
import com.yycx.module.bus.client.entity.hy.BusDeptHy;
import com.yycx.module.bus.provider.mapper.BusSalemanMapper;
import com.yycx.module.bus.provider.service.*;
import com.yycx.module.bus.provider.service.hy.*;
import com.yycx.module.system.client.entity.SysArea;
import com.yycx.module.system.client.entity.SysCompany;
import com.yycx.module.system.provider.service.SysAreaService;
import com.yycx.module.system.provider.service.SysCompanyService;
import com.yycx.module.user.provider.service.AppPositionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 业务员接口实现类
 *
 * @author flyme
 * @date 2020-07-29
 */
@Service
@DSTransactional
public class BusSalemanServiceImpl extends BaseServiceImpl<BusSalemanMapper, BusSaleman> implements BusSalemanService {
    @Resource
    private BusDeptService deptService;

    @Resource
    private BusDeptHyService deptHyService;

    @Resource
    private BusSalemanBankService salemanBankService;

    @Resource
    private SysCompanyService companyService;

    @Resource
    private SysAreaService areaService;

    @Resource
    private AppPositionService positionService;

    @Resource
    private HyRemoteOrderService hyRemoteOrderService;

    @Resource
    private HyErpSearchService hyErpSearchService;

    @Autowired
    @Lazy
    private BusSalemanService salemanService;

    @Autowired
    @Lazy
    private HyOrderDetailService orderDetailService;


    @Autowired
    @Lazy
    private BusSalemanBalanceService salemanBalanceService;


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusSaleman busSaleman, EntityMap extra) {

        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<BusSaleman> cu, BusSaleman busSaleman, EntityMap extra) {

        return super.beforeEdit(cu, busSaleman, extra);
    }

    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, BusSaleman busSaleman, EntityMap extra) {
        return super.afterEdit(cu, busSaleman, extra);
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, BusSaleman busSaleman, EntityMap extra) {
        String bankName = cs.getParams("bankName");
        String bankNo = cs.getParams("bankNo");
        String remark = cs.getParams("remark");
        String saleManName = cs.getParams("saleManName");
        if (FlymeUtils.isNotEmpty(bankName)) {
            BusSalemanBank salemanBank = new BusSalemanBank();
            salemanBank.setBankNo(bankNo);
            salemanBank.setBankName(bankName);
            salemanBank.setRemark(remark);
            salemanBank.setSaleManName(saleManName);
            salemanBank.setSaleManId(busSaleman.getSaleManId());
            salemanBank.setDeptId(busSaleman.getDeptId());
            salemanBank.setBankState(CommonConstants.ENABLED);
            salemanBankService.save(salemanBank);
        }
        return super.afterAdd(cs, busSaleman, extra);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusSaleman> cq, BusSaleman saleman, EntityMap requestMap) {

        return ResultBody.ok();
    }

    @Override
    public List<EntityMap> afterPageList(CriteriaQuery<BusSaleman> cq, List<EntityMap> data, ResultBody resultBody) {
        Long companyId = OpenHelper.getCompanyId();
        for (EntityMap datum : data) {
            BigDecimal amount = new BigDecimal("0");
            Long saleManId = datum.getLong("saleManId");
            BigDecimal totalAmount = salemanBalanceService.totalAmount(saleManId, companyId);
            BigDecimal usedAmount = orderDetailService.totalCustomBondAmount(saleManId, companyId);
            //资保金余额
            amount = FlymeUtils.getBigDecimal(totalAmount.subtract(usedAmount), "0");
            datum.put("amount", amount);

        }
        return super.afterPageList(cq, data, resultBody);
    }

    /**
     * 删除前业务处理
     *
     * @param cd
     * @return
     */
    @Override
    public ResultBody beforeDelete(CriteriaDelete<BusSaleman> cd) {
        EntityMap map = cd.getRequestMap();
        String saleManBusinessNo = map.get("saleManBusinessNo");
        if (FlymeUtils.isNotEmpty(saleManBusinessNo)) {
            List<SysCompany> list = companyService.list(new QueryWrapper<SysCompany>().lambda().eq(SysCompany::getCompanyErpState, 1).ne(SysCompany::getCompanyId, 1017L));
            if (FlymeUtils.isNotEmpty(list)) {
                Integer count = 0;
                for (SysCompany company : list) {
                    count += hyRemoteOrderService.countBySaleManNo(company.getCompanyErpInstance(), saleManBusinessNo);
                }
                ApiAssert.lezero("删除失败,业务员已存在订单", count);
            }
        }
        return super.beforeDelete(cd);
    }

    @Override
    public ResultBody beforeListEntityMap(CriteriaQuery<BusSaleman> cq, BusSaleman saleman, EntityMap requestMap) {
        cq.eq(BusSaleman.class, "deptId");
        cq.eq(true, "salemanState", CommonConstants.ENABLED);
        cq.eq(FlymeUtils.isNotEmpty(saleman.getSaleManType()), "saleManType", saleman.getSaleManType());
        cq.orderByAsc("orderNum");
        return super.beforeListEntityMap(cq, saleman, requestMap);
    }


    /**
     * 删除后业务处理
     *
     * @param cd
     * @param ids
     * @return
     */
    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Serializable[] ids) {
        EntityMap map = cd.getRequestMap();
        String saleManBusinessNo = map.get("saleManBusinessNo");
        Serializable saleManId = cd.getIdValue();
        //删除银行账户
        salemanBankService.deleteBySaleManId(saleManId);
        List<SysCompany> list = companyService.list(new QueryWrapper<SysCompany>().lambda().eq(SysCompany::getCompanyErpState, 1).ne(SysCompany::getCompanyId, 1017L));
        if (FlymeUtils.isNotEmpty(list)) {
            for (SysCompany company : list) {
                hyRemoteOrderService.deleteSaleManByNo(company.getCompanyErpInstance(), saleManBusinessNo);
            }
        }
        return super.afterDelete(cd, ids);
    }


    @Override
    public List<BusSaleman> selectList(Long deptId, Boolean hasSelf) {
        CriteriaQuery cq = new CriteriaQuery(BusSaleman.class);
        cq.eq(true, "dept", deptId);
        return list(cq);
    }

    @Override
    public BusSaleman getBySaleManBusinessNo(Long deptId, String saleManBusinessNo) {
        return getOne(new QueryWrapper<BusSaleman>().lambda().eq(BusSaleman::getDeptId, deptId).eq(BusSaleman::getSaleManBusinessNo, saleManBusinessNo), false);
    }

    @Override
    public BusSaleman getBySaleManBusinessNo(String saleManBusinessNo) {
        return getOne(new QueryWrapper<BusSaleman>().lambda().eq(BusSaleman::getSaleManBusinessNo, saleManBusinessNo), false);
    }


    @Override
    public BusSaleman getBySaleManName(Long deptId, String saleManName) {
        return getOne(new QueryWrapper<BusSaleman>().lambda().eq(BusSaleman::getDeptId, deptId).eq(BusSaleman::getSaleManName, saleManName));
    }

    public BusSaleman getBySaleManHyId(String saleManHyId, Long companyId) {
        return getOne(new QueryWrapper<BusSaleman>().lambda().eq(BusSaleman::getCompanyId, companyId).eq(BusSaleman::getSaleManHyId, saleManHyId));
    }

    @Override
    @Async("voucherExecutor")
    public void syncHyData(OpenUser openUser) {
        Long companyId = openUser.getCompanyId();
        SysCompany company = companyService.getById(companyId);
        if (FlymeUtils.isNotEmpty(company)) {
            String dbName = company.getBusinessScope();
            ApiAssert.isNotEmpty("账套实例未配置", dbName);
            List<EntityMap> deptList = hyRemoteOrderService.selectHySaleManList("DBR_YP2018.dbo.");
            for (EntityMap entityMap : deptList) {
                String saleManHyId = entityMap.get("saleManHyId");
                String saleManBusinessNo = entityMap.get("saleManBusinessNo");
                String saleManName = entityMap.get("saleManName");
                String deptNo = entityMap.get("deptNo");
                String orderNum = entityMap.get("orderNum");
                BusSaleman saleman = getBySaleManBusinessNo(saleManBusinessNo);
                if (FlymeUtils.isEmpty(saleman)) {
                    saleman = new BusSaleman();
                    saleman.setCompanyId(5L);
                    saleman.setSaleManBusinessNo(saleManBusinessNo);
                    saleman.setSalemanState(1);
                    saleman.setOrganizationId(OpenHelper.getOrganizationId());
                }
                BusDeptHy dept = deptHyService.getByHyDeptId(deptNo, 1018L);
                if (FlymeUtils.isNotEmpty(dept)) {
                    //saleman.setDeptId(dept.getDeptId());
                }
                saleman.setSaleManType(1);
                saleman.setOrderNum(orderNum);
                saleman.setSaleManBusinessNo(saleManBusinessNo);
                saleman.setSaleManName(saleManName);
                //saleman.setSaleManHyId(saleManHyId);
                if (FlymeUtils.isNotEmpty(saleManBusinessNo) && saleManBusinessNo.length() > 4) {
                    String saleManCode = saleManBusinessNo.substring(saleManBusinessNo.length() - 4);
                    saleman.setSaleManCode(saleManCode);
                }
                saveOrUpdate(saleman);
            }
        }
    }


    @Override
    public String getAreaShortName(BusSaleman busSaleman) {
        //区域简称
        String areaShortName = "";
        //区域名称
        String areaName = "";
        //省份ID
        Long proId = busSaleman.getProId();
        if (FlymeUtils.isNotEmpty(proId)) {
            SysArea sysArea = areaService.getById(proId);
            areaShortName = sysArea.getShortName();
            areaName += sysArea.getAreaName();
            ApiAssert.isNotEmpty("省份编码未设置", areaShortName);
        }

        //城市ID
        Long cityId = busSaleman.getCityId();

        if (FlymeUtils.isNotEmpty(cityId)) {
            SysArea sysArea = areaService.getById(cityId);
            areaShortName = sysArea.getShortName();
            areaName += "-" + sysArea.getAreaName();
            ApiAssert.isNotEmpty("市区编码未设置", areaShortName);
        }

        //区域
        Long areaId = busSaleman.getAreaId();

        if (FlymeUtils.isNotEmpty(areaId)) {
            SysArea sysArea = areaService.getById(areaId);
            areaShortName = sysArea.getShortName();
            areaName += "-" + sysArea.getAreaName();
            ApiAssert.isNotEmpty("区域编码未设置", areaShortName);
        }
        busSaleman.setAreaShortName(areaShortName);
        busSaleman.setAreaName(areaName);
        return areaShortName;
    }


    @Override
    public BigDecimal surplusCustomBondAmount(Long saleManId, Long companyId) {
        BigDecimal amount = new BigDecimal("0");
        BusSaleman saleman = salemanService.getById(saleManId);
        if (FlymeUtils.isNotEmpty(saleman)) {
            //初始金额
            BigDecimal totalAmount = salemanBalanceService.totalAmount(saleManId, companyId);
            //已用金额(已发货未回款的订单占用的额度)
            BigDecimal usedAmount = orderDetailService.totalCustomBondAmount(saleManId, companyId);
            //资保金余额
            amount = FlymeUtils.getBigDecimal(totalAmount.subtract(usedAmount), "0");
        }
        return amount;
    }


    @Override
    public BigDecimal surplusCustomBondAmount(Long saleManId, Long companyId, String orderId) {
        //总金额
        BusSaleman saleman = getById(saleManId);
        BigDecimal amount = new BigDecimal("0");
        if (FlymeUtils.isNotEmpty(saleman)) {
            //余额
            BigDecimal totalAmount = salemanBalanceService.totalAmount(saleManId, companyId);
            //已用金额(已发货未回款的订单占用的额度)
            BigDecimal usedAmount = orderDetailService.totalCustomBondAmount(saleManId, companyId, orderId);
            //资保金余额
            amount = FlymeUtils.getBigDecimal(totalAmount.subtract(usedAmount), "0");
        }

        return amount;
    }

    @Override
    public void syncToHy(Long saleManId) {
        BusSaleman saleman = getById(saleManId);
        Long deptId = saleman.getDeptId();
        BusDept dept = deptService.getById(deptId);
        ApiAssert.isNotEmpty("部门不存在", dept);
        String deptNo = dept.getDeptNo();
        ApiAssert.isNotEmpty("部门自定义编码不存在", deptNo);
        String deptType = dept.getDeptType();
        List<SysCompany> list = companyService.list(new QueryWrapper<SysCompany>().lambda().eq(SysCompany::getCompanyErpState, 1).ne(SysCompany::getCompanyId, 1017L));
        if (FlymeUtils.isNotEmpty(list)) {
            String orderNum = saleman.getOrderNum();
            String saleManBusinessNo = saleman.getSaleManBusinessNo();
            String saleManBusinessPinYinNo = "";
            if (FlymeUtils.isNotEmpty(saleManBusinessNo)) {
                saleManBusinessPinYinNo = PinyinUtil.getPinYinHeadChar(saleManBusinessNo).toUpperCase();
            }
            for (SysCompany company : list) {
                String companName = company.getCompanyName();
                String dbName = company.getCompanyErpInstance();
                BusDeptHy deptHy = deptHyService.getByDeptCode(deptNo, company.getCompanyId());
                ApiAssert.isNotEmpty(companName + "-部门资料不存在", deptHy);
                //海鹰中对应的部门编码
                String hyDeptNo = deptHy.getHyDeptNo();
                ApiAssert.isNotEmpty(companName + "-部门编码不存在", hyDeptNo);
                String checkId = hyErpSearchService.selectHySaleManByBusinessNo(dbName, saleManBusinessNo);
                EntityMap params = new EntityMap();

                params.put("telephone", "");
                params.put("linkMan", "");
                params.put("jhContro", "");
                params.put("xhContro", "");
                if (FlymeUtils.isEmpty(checkId)) {
                    String maxSaleManId = hyErpSearchService.selectHyMaxSaleId(dbName);
                    String nexId = String.format("%09d", Integer.parseInt(maxSaleManId) + 1);
                    params.put("saleManId", nexId);
                    params.put("hyDeptNo", hyDeptNo);
                    params.put("orderNum", orderNum);
                    params.put("saleManName", saleman.getSaleManName());
                    params.put("deptName", dept.getDeptName());
                    params.put("saleManBusinessNo", saleManBusinessNo);
                    params.put("saleManBusinessPinYinNo", saleManBusinessPinYinNo);
                    hyRemoteOrderService.insertHySaleMan(dbName, params);
                } else {
                    Integer count = hyRemoteOrderService.countBySaleManNo(company.getCompanyErpInstance(), saleManBusinessNo);
                    Integer orderCount = FlymeUtils.getInteger(count, 0);
                    if (orderCount.equals(0)) {
                        params.put("hyDeptNo", hyDeptNo);
                        params.put("orderNum", orderNum);
                        params.put("saleManName", saleman.getSaleManName());
                        params.put("deptName", dept.getDeptName());
                        params.put("saleManBusinessNo", saleManBusinessNo);
                        params.put("saleManBusinessPinYinNo", saleManBusinessPinYinNo);
                    }
                    params.put("saleManId", checkId);
                    hyRemoteOrderService.updateHySaleMan(dbName, params);
                }
            }
        }
    }

    @Override
    public Boolean updateAmount(Map params) {
        Long saleManId = MapUtil.get(params, "saleManId", Long.class);
        BigDecimal reputationAmount = MapUtil.get(params, "reputationAmount", BigDecimal.class);
        Integer number = MapUtil.getInt(params, "number");
        BigDecimal amount = MapUtil.get(params, "amount", BigDecimal.class);
        CriteriaUpdate cu = new CriteriaUpdate();
        if (FlymeUtils.isNotEmpty(number)) {
            cu.set(true, "number", number);
        }
        if (FlymeUtils.isNotEmpty(reputationAmount)) {
            cu.set(true, "reputationAmount", reputationAmount);
        }
        cu.eq(true, "saleManId", saleManId);
        boolean tag = update(cu);
        if (FlymeUtils.isNotEmpty(amount)) {
            if (FlymeUtils.isNotEmpty(amount)) {
                salemanBalanceService.saveSalManBalance(saleManId, amount);
            }
        }
        return tag;
    }

    @Override
    public void updateProLevel(Integer proLevel, Long deptId) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "proLevel", proLevel);
        cu.eq(true, "deptId", deptId);
        cu.eq(true, "saleManType", 2);
        Boolean result = update(cu);
    }

    @Override
    public void updateSaleManState(Long saleManId, String processInstanceId, Integer saleManState) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "saleManState", saleManState);
        cu.set(true, "processInstanceId", processInstanceId);
        cu.eq(true, "saleManId", saleManId);
        Boolean result = update(cu);
    }

}
